Bug 7100996

Bug Description:

This is a race bug. Expected exception is: java.lang.IndexOutOfBoundsException.
This bug happens when an instance of StringBuffer calls insert and deleteCharAt in 2 threads separately.
More details about this bug are at JDK-7100996 JIRA page.

Interleaving Description:

The numbers in the following code snippets present the global execution sequence.

java.lang.StringBuffer:

t1  t2  public StringBuffer insert(int dstOffset, CharSequence s) {
            // Note, synchronization achieved via other invocations
            if (s == null)
                s = "null";
            if (s instanceof String)
                return this.insert(dstOffset, (String)s);
1           return this.insert(dstOffset, s, 0, s.length());
        }
        
        public synchronized StringBuffer insert(int dstOffset, CharSequence s, 
                            int start, int end)
        {
4           super.insert(dstOffset, s, start, end);
            return this;
        }
    
        public synchronized StringBuffer deleteCharAt(int index) {
    2       super.deleteCharAt(index);
    3       return this;
        }

Precondition: an instance of StringBuffer serves as both source and target at inserting. For example:

        StringBuffer sb=new StringBuffer("abc");
thread1:
        sb.insert(1,sb);
thread2:
        sb.deleteCharAt(0);
    

a) thread 1 comes to 1 and obtains the value of s.length(). Let's assume s.length() is L now.
b) before thread 1 continues to call this.insert at 1 to obtain lock, context switched, thread 2 deletes a char and returns at 2 and 3.
c) context switched, thread 1 continues to 4. As s has been modified at step 2, now its length is L-1, but parameter "end" is still L.
d) thread 1 calls super.insert and an IndexOutOfBoundsException is thrown due to end (value is L) is bigger than s.length() (value is L-1).

How To Reproduce:

This bug is reproduced under JDK 1.6.0.
It started at JDK 1.6.0, and has been fixed since JDK 1.8.0.
Execute the following scripts to run the test to reproduce the bug (assume the location of the jdk6 test project is jdk_test_home).

Linux:
${jdk_test_home}/scripts/7100996.sh [--javaloc path]
Windows:
%jdk_test_home%\scripts\7100996.bat [--javaloc path]

Option Function
--javaloc The location of JDK that is eligible to reproduce the bug, if your java environment is not eligible.
In this case, it's JDK 1.6.0. It should be the absolute path to the JDK's java starter and ended with "/".
For example: ~/jdk/home/jdk1.6.0/bin/